package com.unitd.base.frame.util;

import org.springframework.util.Assert;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.TreeMap;

/**
 * 自定义的Map工具类,处理与Map相关的公共信息
 *
 * @author Hudan
 * @version 1.0
 * @filename MapUtils.java
 * @copyright www.unitd.com
 * @date 2020/4/20
 */
public class MapUtils extends org.apache.commons.collections.MapUtils {

    /**
     * 判断指定的map对象是否为空
     *
     * @param dataMap mao集合对象
     * @return boolean
     */
    public static boolean isNull(Map dataMap) {
        return dataMap == null || dataMap.isEmpty();
    }

    /**
     * 用org.apache.commons.beanutils 工具类实现 Map --> Bean(一般情况下建议使用此方法,不建议使用map2Bean2方法)
     *
     * @param map map对象
     * @param obj 转换后的Bean对象
     */
    public static void toBean(Map<String, Object> map, Object obj) {
        if (map == null || obj == null) {
            return;
        }
        try {
            org.apache.commons.beanutils.BeanUtils.populate(obj, map);
        } catch (Exception e) {
            System.out.println("transMap2Bean2 Error " + e);
            e.printStackTrace();
        }
    }

    /**
     * 利用Introspector,PropertyDescriptor实现 Map --> Bean
     *
     * @param map map对象
     * @param obj 转换后的Bean对象
     */
    public static void toBean2(Map<String, Object> map, Object obj) {
        String key = null;
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                key = property.getName();

                if (map.containsKey(key)) {
                    Object value = map.get(key);
                    // 得到property对应的setter方法
                    Method setter = property.getWriteMethod();
                    setter.invoke(obj, value);
                }
            }
        } catch (Exception e) {
            System.out.println("map2Bean2 Error " + e + ",KEY:" + key);
            e.printStackTrace();
        }
    }

    /**
     * 根据key的前缀,获取类似key前缀的子Map对象
     *
     * @param mapData 需要进行截取的map对象
     * @param prefix  key的前缀
     * @return Map
     */
    public static Map<String, Object> getSonMapByStartsWith(Map<String, Object> mapData, String prefix) {
        Assert.notNull(mapData, "map data must not be null");

        Map<String, Object> params = new TreeMap();
        if (prefix == null) {
            prefix = "";
        }

        for (String paramName : mapData.keySet()) {
            if ("".equals(prefix) || paramName.startsWith(prefix)) {
                params.put(paramName, mapData.get(paramName));
            }
        }
        return params;
    }

    /**
     * 根据key的前缀,获取类似key前缀的子Map对象,并且key值为截取掉前缀之后的key
     *
     * @param mapData 需要进行截取的map对象
     * @param prefix  key的前缀
     * @return Map
     */
    public static Map<String, Object> getMapByStartsWith(Map<String, Object> mapData, String prefix) {
        Assert.notNull(mapData, "map data must not be null");

        Map<String, Object> params = new TreeMap();
        if (prefix == null) {
            prefix = "";
        }

        for (String paramName : mapData.keySet()) {
            if ("".equals(prefix) || paramName.startsWith(prefix)) {
                String unprefixed = paramName.substring(prefix.length());
                params.put(unprefixed, mapData.get(paramName));
            }
        }
        return params;
    }

    /**
     * 根据key判断指定map集合中是否存在对应的key
     *
     * @param dataMap  指定的map集合
     * @param checkKey 需要判断的key
     * @return boolean
     */
    public static boolean checkKeyExist(Map<String, Object> dataMap, String checkKey) {
        for (String key : dataMap.keySet()) {
            if (checkKey.equals(key)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 根据key判断指定map集合中是否存在对应的忽略大小写的key
     *
     * @param dataMap  指定的map集合
     * @param checkKey 需要判断的key
     * @return boolean
     */
    public static boolean checkKeyIgnoreCaseExist(Map<String, Object> dataMap, String checkKey) {
        for (String key : dataMap.keySet()) {
            if (checkKey.equalsIgnoreCase(key)) {
                return true;
            }
        }
        return false;
    }
}